#!/usr/bin/python
#########################################################
#						Welcome							#
#					Tip-system in Python				#
#					 Version: v1.1 						#
#					Date: 2015/04/10					#
#			By: Haoyu hu	Email: im@huhaoyu.com		#
#			Address: Tsinghua University				#
#########################################################
import sys, time
import smtplib, poplib
import email.mime.multipart, email
import email.mime.text, base64
import re, getpass, os, getopt, string

autograph = '\nName\t\t: Haoyuhu\nAddress\t\t: Tsinghua University\nTelephone\t: 15201524605\nDepartment\t: Civil Engineering\n'
pop_servername_store = {'163.com': 'pop3.163.com', 'qq.com': 'pop3.qq.com', 'huhaoyu.com': 'pop.ym.163.com'}
smtp_servername_store = {'163.com': 'smtp.163.com', 'qq.com': 'smtp.qq.com', 'huhaoyu.com': 'smtp.ym.163.com'}
#send and receive mail
#########################################################
#				Mail Assistant Module					#
#########################################################
def get_servername(mailbox, smtp_or_pop):
	_, domain_name = mailbox.split('@')
	if smtp_or_pop:
		return smtp_servername_store[domain_name]
	else:
		return pop_servername_store[domain_name]
def sub(mail):
	ret = ''
	add_list = re.findall('[a-zA-Z0-9][\w\.-]+@(?:[A-Za-z0-9]+\.)+[A-Za-z]+', mail)
	for line in add_list:
		ret += line + '\n'
	ret = ret[:len(ret)-1]
	return ret

def send_mail(from_box, password, to_box, subject, content):
	msg = email.mime.multipart.MIMEMultipart()
	msg['from'] = from_box
	msg['to'] = to_box
	msg['subject'] = subject

	text = email.mime.text.MIMEText(content, 'plain', 'utf-8')
	msg.attach(text)

	try:
		server = smtplib.SMTP(get_servername(from_box, True), 25)
		server.login(from_box, password)
		server.sendmail(from_box, to_box, str(msg))
	except SMTPException:
		print 'ERROR: LOGIN FAILED'
		sys.exit(1)

	server.quit()

def receive_mail(username, password):
	servername = get_servername(username, False)

	#enter server
	server = poplib.POP3(servername)
	#server.set_debuglevel(1)
	server.user(username)
	server.pass_(password)

	#print mail infomation
	mails_num, _ = server.stat()
	print '**' + username + '\'s Inbox' + '**'
	print 'total email number is %d' %(mails_num)
	print 'time: ' + time.strftime('%Y-%m-%d %H:%M:%S')
	print

	lines = []
	for index in range(mails_num):
		print '**New Message %d**' %(index + 1)
		message = server.retr(index + 1)[1]
		mail = email.message_from_string(string.join(message, '\n'))
		from_mail = sub(mail['from'])
		to_mail =  sub(mail['to'])
		date = mail['date']
		subject = email.Header.decode_header(mail['subject'])[0][0]
		subcode = email.Header.decode_header(mail['subject'])[0][1]
		if subcode != None:
			subject = unicode(subject, subcode)
		print 'From: %s' %from_mail
		print 'To: %s' %to_mail
		print 'Date: %s' %date
		print 'Subject: %s\n' %subject

	server.quit()
	return mails_num

def delete_mail(username, password):
	servername = get_servername(username, False)

	mails_num = receive_mail(username, password)
	if mails_num == 0:
		print 'No mail at server, quit now!\n'
		sys.exit(0)
	
	while True:
		index = raw_input('Please input the mail index that you want to delete(q to quit): ')
		if index == 'q':
			print 'Now quit Tip-System(Mailbox Modules)\n'
			sys.exit(0)
		index = int(index)
		if index >= 1 and index <= mails_num:
			break

	#enter server
	server = poplib.POP3(servername)
	#server.set_debuglevel(1)
	server.user(username)
	server.pass_(password)
	server.dele(index)
	server.quit()

	print 'Deleted successfully!\n'
	return mails_num - 1

#########################################################
#					Mail Main Module					#
#########################################################

def send(do_input):
	print 'Please input your from_mailbox, password, to_mailbox, subject and content'
	from_box = 'im@huhaoyu.com'
	password = 'your_password'

	if do_input:
		while True:
			from_box = raw_input('From_mailbox(username@domain.com, \'q\' to quit): ')
			if re.search('\w+@\w+\.com', from_box) != None:
				break
			if from_box == 'q':
				print 'Now quit Tip-System(Mailbox Modules)'
				sys.exit(0)
			print 'Input error, try again!\n'

		password = getpass.getpass('Password: ')

	while True:
		to_box = raw_input('To_mailbox(username@domain.com, \'q\' to quit): ')
		if re.search('\w+@\w+\.com', to_box) != None:
			break
		if from_box == 'q':
			print 'Now quit Tip-System(Mailbox Modules)'
			sys.exit(0)
		print 'Input error, try again!\n'

	subject = raw_input('Subject: ')

	content = ''
	print 'Content(\'q\' to quit): '
	while True:
		line = raw_input('>>>')
		if line == 'q':
			break
		else:
			content += line + '\r\n'
	content += autograph

	print 'Please wait while being sent...'
	send_mail(from_box, password, to_box, subject, content)
	print 'Sent successfully!\n'

def receive(do_input):
	mailbox = 'im@huhaoyu.com'
	password = 'your_password'

	if do_input:
		print 'Please input your mailbox, password'
		
		while True:
			mailbox = raw_input('Mailbox(username@domain.com, \'q\' to quit): ')
			if re.search('\w+@\w+\.com', mailbox) != None:
				break
			if mailbox == 'q':
				print 'Now quit Tip-System(Mailbox Modules)'
				sys.exit(0)
			print 'Input error, try again!\n'

		password = getpass.getpass('Password: ')

	print 'FETCHING DATA FROM THE SERVER, PLEASE WAIT A MOMENT...'
	receive_mail(mailbox, password)

def delete(do_input):
	mailbox = 'im@huhaoyu.com'
	password = 'your_password'

	if do_input:
		print 'Please input your mailbox, password'
		
		while True:
			mailbox = raw_input('Mailbox(username@domain.com, \'q\' to quit): ')
			if re.search('\w+@\w+\.com', mailbox) != None:
				break
			if mailbox == 'q':
				print 'Now quit Tip-System(Mailbox Modules)'
				sys.exit(0)
			print 'Input error, try again!\n'

		password = getpass.getpass('Password: ')

	while True:
		print 'FETCHING DATA FROM THE SERVER, PLEASE WAIT A MOMENT...'
		remain = delete_mail(mailbox, password)
		print 'Now the mails number is %d' %remain
		if remain == 0:
			print 'No mail at server, quit now!'
			break
		continue_delete = raw_input('Do you want to continue to remove other mails? [Y/n]: ')
		if continue_delete == '' or continue_delete.lower()[0] != 'y':
			break

#########################################################
#					Tip Main Module						#
#########################################################
relative_path = 'TIP_STORE.txt'

def create_path():
 	base_path = os.path.abspath(os.path.dirname(sys.argv[0]))
 	return os.path.join(base_path, relative_path)

def show_tip():
	file_handler = open(create_path(), 'r')
	tip_list = file_handler.readlines()
	file_handler.close()

	print '**Your Tips In Tip-store**'
	if tip_list == []:
		print 'No data in tip-store\n'
		return 0, []
	else:
		for i in range(len(tip_list)):
			line = tip_list[i]
			tip_list[i] = line[:len(line)-1]

		count = 0
		for tip in tip_list:
			count += 1
			print 'Tip %d: %s' %(count, tip)

	
	return count, tip_list

def clear_tip():
	file_handler = open(create_path(), 'w')
	file_handler.close()
	print 'Clear successfully!\n'

def save_tip(tip):
	if tip == '':
		print 'Tip is null\n'
		return
	file_handler = open(create_path(), 'a')
	file_handler.write(tip + '\n')
	file_handler.close()
	print 'Save tip successfully!\n'

def modify_delete_add_tip(modify_or_delete_or_add):
	count, tip_list = show_tip()
	if modify_or_delete_or_add == 0:
		operation = 'modify'
	elif modify_or_delete_or_add == 1:
		operation = 'delete'
	elif modify_or_delete_or_add == 2:
		operation = 'add'
	if count == 0:
		print 'No tip could be %s, now quit!\n' %operation
		return
	index = raw_input('Which tip do you want to %s(q to quit): ' %operation)
	if index == 'q':
		print 'Now quit the tip-system\n'
		return
	while int(index) > count or int(index) < 1:
		index = raw_input('Input error, try again(q to quit): ')
	
	if modify_or_delete_or_add == 0:
		content = raw_input('New tip content: ')
	elif modify_or_delete_or_add == 2:
		content = raw_input('Addition tip content: ')

	file_handler = open(create_path(), 'w')
	
	for cnt in range(count):
		if cnt == int(index) - 1:
			if modify_or_delete_or_add == 0:
				file_handler.write(content + '\n')
			elif modify_or_delete_or_add == 2:
				file_handler.write(tip_list[cnt] + ' --> New(%s): %s\n' %(time.strftime('%Y-%m-%d %H:%M:%S'), content))
		else:
			file_handler.write(tip_list[cnt] + '\n')

	file_handler.close()
	if modify_or_delete_or_add == 0:
		print 'Modified successfully!\n'
	elif modify_or_delete_or_add == 1:
		print 'Deleted successfully!\n'
	else:
		print 'Added successfully!\n'

def modify_tip():
	modify_delete_add_tip(0)

def delete_tip():
	modify_delete_add_tip(1)

def add_tip():
	modify_delete_add_tip(2)

#########################################################
#				Other Assistant Module					#
#########################################################

def help():
	print '-h, --help   : show all options of tip-system'
	print '-v, --version: show version of tip-system'
	print '-i           : input other username and password(otherwise using default)'
	print '--send       : send an email to an email address'
	print '--receive    : receive the emails in your inbox'
	print '--delete     : delete an email in your inbox'
	print '-s           : input your tip after \'-s\''
	print '-a           : add your tips'
	print '-m           : modify your tips'
	print '-d           : delete your tips'
	print '-c           : clear your tip-store'

def version():
	print 'Tip-system Version 1.1\n'

def others():
	print 'What options do you want?'
	help()
	print 'if any unknown error, please contact im@huhaoyu.com\n'

#########################################################
#						Main Module						#
#########################################################
def pytip():
	try:
		options, args = getopt.getopt(sys.argv[1:], 'chvs:imda', ['help', 'version', 'send', 'receive', 'delete'])
	except getopt.GetoptError:
		others()
		sys.exit(1)

	name, value = None, None
	do_input = False
	do_send, do_receive, do_delete= False, False, False

	if options == []:
		show_tip()
		sys.exit(0)

	for name, value in options:
		if name in ('-h', '--help'):
			help()
			sys.exit(0)
		elif name in ('-v', '--version'):
			version()
			sys.exit(0)
		elif name == '-i':
			do_input = True
		elif name == '--send':
			do_send = True
		elif name == '--receive':
			do_receive = True
		elif name == '--delete':
			do_delete = True
		elif name == '-s':
			save_tip(value)
			sys.exit(0)
		elif name == '-m':
			modify_tip()
			sys.exit(0)
		elif name == '-d':
			delete_tip()
			sys.exit(0)
		elif name == '-a':
			add_tip()
			sys.exit(0)
		elif name == '-c':
			clear_tip()
			sys.exit(0)

	if do_send:
		send(do_input)
	elif do_receive:
		receive(do_input)
	elif do_delete:
		delete(do_input)

if __name__ == '__main__':
	pytip()